home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
oper_sys
/
prospero
/
propsero.lha
/
prospero-beta.4.2e
/
user
/
als.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-09
|
10KB
|
506 lines
/*
** A simple fast ls(1) replacement for Prospero. Only supports
** a small subset of the multitude of ls options.
**
** A quick whip-up for the Prospero FTPD.
**
** Steve Cliffe
** Department of Computer Science
** University of Wollongong
** Australia
**
** steve@cs.uow.edu.au
**
** January 1992
*/
#include <stdio.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <search.h>
#include <pfs.h>
#include <pcompat.h>
#include <perrno.h>
#define TABSIZE 500 /* Max number of subdirs */
#define DAYSPERNYEAR (365)
#define SECSPERDAY (60*60*24)
int perrno;
int pfs_debug = 0;
extern int optind;
int opt_long = 0; /* Listing options */
int opt_revsort = 0;
int opt_timesort = 0;
int opt_recursive = 0;
int opt_prospero = 0;
int opt_union = 0;
char *progname;
struct my_stat { /* Info about a file */
unsigned st_size;
unsigned st_blocks;
long st_links;
mode_t st_mode;
time_t st_mtime;
char st_owner[12];
char st_group[12];
char st_modes[12];
};
struct tabent {
char name[128]; /* Link name */
char host[128]; /* Link's host */
char filename[128]; /* Link's system level filename */
long magic_no; /* Link's magic number */
};
struct tabent table[TABSIZE]; /* Cycle detection table */
unsigned int table_entries = 0;
unsigned int table_width = sizeof(struct tabent);
main(argc,argv)
int argc;
char *argv[];
{
int opt;
progname = argv[0];
while ((opt = getopt(argc, argv, "lgrtRPU")) != EOF) {
switch (opt) {
case 'l':
opt_long = 1;
break;
case 'r':
opt_revsort = 1;
break;
case 't':
opt_timesort = 1;
break;
case 'R':
opt_recursive++;
break;
case 'P':
opt_prospero = 1;
break;
case 'U':
opt_union = 1;
break;
default:
fprintf(stderr,
"Usage: %0 [-lrtR] [file or directory name]\n", progname);
exit(1);
}
}
argc -= optind;
argv += optind;
list_directory(argc ? *argv : "");
exit(0);
}
/*
** list_directory:
**
** List out a directory. (i.e. do all the work)
*/
list_directory(path)
char *path;
{
VDIR_ST dir_st;
VDIR dir= &dir_st;
VLINK l;
int flags = GVD_LREMEXP;
int error, been_here, old_table_size;
char newpath[MAXPATHLEN];
struct tabent newent;
int compare();
vdir_init(dir);
if (opt_union)
flags = GVD_UNION;
if (opt_long)
flags |= GVD_ATTRIB;
error = rd_vdir(path, 0, dir, flags);
if(error && (error != DIRSRV_NOT_DIRECTORY)) {
fprintf(stderr, "%s", progname);
perrmesg(" failed: ", error, NULL);
exit(1);
}
if(pwarn)
pwarnmesg("WARNING: ", 0, NULL);
/*
** Display this directory.
*/
l = dir->links;
while(l) {
display_link(l);
l = l->next;
}
/*
** Handle union links.
*/
l = dir->ulinks;
if ((error != DIRSRV_NOT_DIRECTORY))
while(l) {
if ((l->expanded == FALSE) || (l->expanded == FAILED))
display_link(l);
l = l->next;
}
/*
** Display subdirectories if requested (-R).
*/
if (opt_recursive) {
l = dir->links;
while (l) {
/*
** Make sure we haven't been here before.
*/
strcpy(newent.name, l->name);
strcpy(newent.host, l->host);
strcpy(newent.filename, l->filename);
newent.magic_no = l->f_magic_no;
if (table_entries == TABSIZE) {
fprintf(stderr, "%s: cycle detection table overflow\n", progname);
exit(1);
}
old_table_size = table_entries;
been_here = 0;
/*
** Don't cross machine boundaries
** unless -R option is specified twice.
*/
if (strcmp(table[table_entries].host, l->host) &&
(opt_recursive != 2))
goto next;
/*
** Make sure we haven't been here before.
*/
lsearch((char *) &newent, (char *) &table[0], &table_entries,
table_width, compare);
if (old_table_size == table_entries)
been_here = 1;
if ((strcmp(l->type, "DIRECTORY") == 0) && (!been_here)) {
if (path[0] == '\0')
strcpy(newpath, l->name);
else
sprintf(newpath, "%s/%s", path, l->name);
printf("\n%s:\n", newpath);
list_directory(newpath);
}
next:
l = l->next;
}
}
vllfree(dir->links);
return;
}
/*
** display_link:
**
** Display a link based on what options have been selected.
*/
display_link(l)
VLINK l;
{
if (opt_long) {
if (opt_prospero)
display_prospero_long(l);
else
display_long(l);
return;
}
if (opt_prospero)
printf("%c%c %-20.20s %c%-15.15s %-38.38s\n",
((l->linktype == 'L') ? ' ' : l->linktype),
(l->expanded ? 'F' : ' '),
l->name,
(l->filters ? '*' : ' '),
l->host,l->filename);
else
printf("%s\n", l->name);
}
/*
** display_long:
**
** Print out a directory tabent in the UNIX ls -l format. Code to
** fill in the stat(2) buffer based on lib/pcompat/stat.c
*/
display_long(l)
VLINK l;
{
PATTRIB ap, apnext;
struct my_stat stat_buffer;
struct my_stat *sbp = &stat_buffer;
char mode_string[15];
int size;
sbp->st_size = 0;
sbp->st_mtime = (time_t) 0;
strcpy(sbp->st_owner, "-");
strcpy(sbp->st_group, "-");
sbp->st_mode = 0;
sbp->st_modes[0] = '\0';
if (strcmp(l->type, "DIRECTORY") == 0)
sbp->st_mode |= (S_IFDIR | 0555);
else
sbp->st_mode |= 0444;
sbp->st_links = 1;
ap = NULL;
if (l->lattrib == NULL)
ap = pget_at(l, "ALL");
if ((ap == NULL) && (l->lattrib)) {
ap = l->lattrib;
l->lattrib = NULL;
}
while (ap) {
if ((strcmp(ap->aname, "SIZE") == 0) &&
(strcmp(ap->avtype, "ASCII") == 0)) {
sscanf(ap->value.ascii, "%d", &size);
sbp->st_size = size;
sbp->st_blocks = (size + 511) / 512;
}
if ((strcmp(ap->aname, "NATIVE-OWNER") == 0) &&
(strcmp(ap->avtype, "ASCII") == 0))
strcpy(sbp->st_owner, ap->value.ascii);
if ((strcmp(ap->aname, "NATIVE-GROUP") == 0) &&
(strcmp(ap->avtype, "ASCII") == 0))
strcpy(sbp->st_group, ap->value.ascii);
if ((strcmp(ap->aname, "UNIX-MODES") == 0) &&
(strcmp(ap->avtype, "ASCII") == 0))
strcpy(sbp->st_modes, ap->value.ascii);
if ((strcmp(ap->aname, "LAST-MODIFIED") == 0) &&
(strcmp(ap->avtype, "ASCII") == 0))
sbp->st_mtime = asntotime(ap->value.ascii);
apnext = ap->next;
atfree(ap);
ap = apnext;
}
/*
** Now display the tabent.
*/
if (sbp->st_modes[0] == '\0')
(void) strmode(sbp->st_mode, mode_string);
else
strcpy(mode_string, sbp->st_modes);
printf("%s %3u %-8s %-8s %8u ", mode_string, sbp->st_links,
sbp->st_owner, sbp->st_group, sbp->st_size);
printtime(sbp->st_mtime);
printf("%s\n", l->name);
}
/*
** display_prospero_long:
**
** Print out verbose information about a link. Taken from vls.c
*/
display_prospero_long(l)
VLINK l;
{
VLINK fil;
PATTRIB ap;
printf("\n Name: %s\n",l->name);
printf(" ObjType: %s\n",l->type);
printf(" LinkType: %s\n",((l->linktype == 'U') ? "Union" : "Standard"));
printf(" HostType: %s\n",l->hosttype);
printf(" Host: %s\n",l->host);
printf(" NameType: %s\n",l->nametype);
printf(" Pathname: %s\n",l->filename);
if(l->version)
printf(" Version: %d\n",l->version);
if(l->f_magic_no)
printf(" Magic: %d\n",l->f_magic_no);
if (opt_long) { /* Show attributes and filters */
ap = NULL;
if (l->lattrib == NULL)
ap = pget_at(l, "ALL");
if ((ap == NULL) && (l->lattrib)) {
ap = l->lattrib;
l->lattrib = NULL;
}
printf("Attributes:\n\n");
while(ap) {
printf("%15s: ",ap->aname);
if (strcmp(ap->avtype,"ASCII") == 0)
printf("%s\n",ap->value.ascii);
else if (strcmp(ap->avtype,"LINK") == 0)
printf("%s %s %s %d %d\n",
ap->value.link->name,ap->value.link->host,
ap->value.link->filename,
ap->value.link->version,
ap->value.link->f_magic_no);
else
printf("<unknown-type %s>\n",ap->avtype);
ap = ap->next;
}
printf("\n");
atlfree(ap);
if(l->filters) {
printf(" Filters: \n");
fil = l->filters;
while(fil) {
printf("\n HostType: %s\n",fil->hosttype);
printf(" Host: %s\n",fil->host);
printf(" NameType: %s\n",fil->nametype);
printf(" Pathname: %s\n",fil->filename);
if (fil->f_magic_no)
printf(" Magic: %d\n",fil->f_magic_no);
if (fil->args)
printf(" Args: %s\n",fil->args);
fil = fil->next;
}
}
printf("\n");
}
}
/*
** compare - Compare 2 nodes to detect a cycle.
*/
compare(one, two)
struct tabent *one, *two;
{
if (strcmp(one->name, two->name))
return(1);
if (strcmp(one->host, two->host))
return(1);
if (strcmp(one->filename, two->filename))
return(1);
if ((one->magic_no == 0) || (two->magic_no == 0) ||
(one->magic_no == two->magic_no))
return(0);
else
return(1);
}
/* ---------------------------------------------------------- */
/*
** strmode - Pinched from BSD ls.
*/
strmode(mode,modestr)
short mode;
char *modestr;
{
strcpy(modestr,"----------");
if(mode & S_IFDIR) modestr[0] = 'd';
if((mode & S_IFLNK) == S_IFLNK) modestr[0] = 'l';
if(mode & S_IREAD) modestr[1] = 'r';
if(mode & S_IWRITE) modestr[2] = 'w';
if(mode & S_IEXEC) modestr[3] = 'x';
if(mode & S_ISUID) modestr[3] = 's';
if(mode & (S_IREAD>>3)) modestr[4] = 'r';
if(mode & (S_IWRITE>>3)) modestr[5] = 'w';
if(mode & (S_IEXEC>>3)) modestr[6] = 'x';
if(mode & S_ISGID) modestr[6] = 's';
if(mode & (S_IREAD>>6)) modestr[7] = 'r';
if(mode & (S_IWRITE>>6)) modestr[8] = 'w';
if(mode & (S_IEXEC>>6)) modestr[9] = 'x';
}
/*
** printtime - pinched from the BSD ls.
*/
printtime(ftime)
time_t ftime;
{
int i;
char *longstring, *ctime();
time_t time();
if(ftime == 0) fputs("- ",stdout);
else {
DISABLE_PFS(longstring = ctime((long *)&ftime));
for (i = 4; i < 11; ++i)
(void)putchar(longstring[i]);
#define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
if (ftime + SIXMONTHS > time((time_t *)NULL))
for (i = 11; i < 16; ++i)
(void)putchar(longstring[i]);
else {
(void)putchar(' ');
for (i = 20; i < 24; ++i)
(void)putchar(longstring[i]);
}
(void)putchar(' ');
}
}